
#include <BFont>
#include <BFile>
#include "IGlobal.h"
#include "member_BFont.h"

using namespace BWE;

BMap<BString, FontFamilyHolder>& FontFamilyMap()
{
	static BMap<BString, FontFamilyHolder> familyMap;
	return familyMap;
}

member_BFont::member_BFont(BFont* font)
{
	boss = font;
	bold = false;
	italic = false;
	underline = false;
	spaceSize = -1;
	tabSize = -1;
}
member_BFont::~member_BFont()
{

}

bool member_BFont::loadFamily()
{
	auto& familyMap = FontFamilyMap();
	IFontFamily* font_family = familyMap(family);
	if (font_family)
	{
		fontFamily = font_family;
		return true;
	}
	BString fontFileName;
	if (fontFileName.empty())
	{
		for (int i = 0; i < app_fontPaths.size(); i++)
		{
			BString fileName = app_fontPaths[i];
			fileName << '/' << family << ".ttf";
			if (BFile::Exists(fileName))
			{
				fontFileName = fileName;
				break;
			}
		}
	}
	if (fontFileName.empty())
	{
		BString fileName = app_libPath;
		fileName << "/font/" << family << ".ttf";
		if (BFile::Exists(fileName))
			fontFileName = fileName;
	}
	if (fontFileName.empty())
	{
		BString fileName("./font");
		fileName << '/' << family << ".ttf";
		if (BFile::Exists(fileName))
			fontFileName = fileName;
	}

	if (fontFileName.empty())
		return false;

	fontFamily = new IFontFamily(fontFileName);
	familyMap[family] = fontFamily;
	return true;
}

CodeInfo* member_BFont::getCodeInfo(BCode code)
{
	if (code == 13)
		code = 164;

	if (!fontFamily)
		return 0;

	if (troubleCodes.contain(code))
		return 0;

	auto it = table.find(code);
	if (it.valid())
		return &(*it);

	CodeInfo& info = table[code];
	if(!fontFamily->image(code, size, info))
		troubleCodes.append(code);

	return &info;
}

BSize member_BFont::codeSize(BCode code)
{
	if (code == '\n')
		return size;

	if (code == 13)
		code = 164;

	if (code == ' ')
	{
		if(spaceSize > 0)
			return BSize(spaceSize, size.height());
		return BSize(size.width()/2, size.height());
	}

	if(code == '\t')
	{
		if (tabSize > 0)
			return BSize(tabSize, size.height());
		return BSize(size.width() * 2, size.height());
	}

	CodeInfo* info = getCodeInfo(code);
	if (!info)
		return size;

	const BImage* bitmap = info->bitmap.ptr();
	if (!bitmap)
		return size;

	int width = info->left + bitmap->width();

	return BSize(width, size.height());
}
